package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.repository.StrategyTmplateRepository;
import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.service.IStrategySearchService;
import cn.wolfcode.luowowo.search.template.StrategyTemplate;
import cn.wolfcode.luowowo.search.vo.SearchResult;
import cn.wolfcode.luowowo.search.vo.StatsResult;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service//
public class StrategySearchServiceImpl implements IStrategySearchService{

    @Autowired
    private StrategyTmplateRepository repository;

    @Override//.....
    public void save(StrategyTemplate template) {
        repository.save(template);
    }

    @Override
    public Page<StrategyTemplate> queryForList(SearchQueryObject qo) {
        Page<StrategyTemplate> page=null;
        switch (qo.getType()){
            case SearchQueryObject.CONDITION_UNABROAD:
                //国内 根据国内查询
                page=repository.findByCountryId(qo.getTypeValue(),qo.getPageable()); break;
            case SearchQueryObject.CONDITION_ABROAD:
                //国外 根据国外查询
                page=repository.findByProvinceId(qo.getTypeValue(),qo.getPageable()); break;
            case SearchQueryObject.CONDITION_THEME:
                //主题 根据主题 查询
                page=repository.findByThemeId(qo.getTypeValue(),qo.getPageable()); break;
            default:
                //默认没有选择条件,则查询所有
                page=repository.findAll(qo.getPageable());
        }
        return page;
    }

    @Override
    public List<StatsResult> listCondition(int conditionTheme) {
        String id=null;
        String name=null;
        switch(conditionTheme){
            case SearchQueryObject.CONDITION_UNABROAD:
                //国内查询,按照省份做查询
                id="provinceId";
                name="provinceName"; break;
            case SearchQueryObject.CONDITION_ABROAD:
                //国外查询,按照国家做查询
                id="countryId";
                name="countryName"; break;
            case SearchQueryObject.CONDITION_THEME:
                //主题 查询
                id="themeId";
                name="themeName"; break;
        }
        return groupSearch(id,name);
    }

    @Override
    public List<Map<String, Object>> listThemeCommendTop10() {
        List<Map<String, Object>> list= new ArrayList<>();
        //查询所有主题捅聚合结果
        List<StatsResult> vos = groupSearch("themeId", "themeName");
        Collections.sort(vos,(o1,o2)->{
            Long val = o2.getCount() - o1.getCount();
            return val.intValue();
        });
        //只要前10个
        if(vos.size()>10){
            vos=vos.subList(0,10);
        }
        for(StatsResult vo:vos){
            HashMap<String, Object> map = new HashMap<>();
            map.put("theme",vo);
            //根据主题id,查出攻略目的地
            List<StrategyTemplate> sts = repository.findByThemeId(vo.getId(), null).getContent();
            HashSet<StatsResult> set = new HashSet<>();
            for (StrategyTemplate st:sts){
                //StatsResult底层重写了hashCode和equals方法
                set.add(new StatsResult(st.getDestId(),st.getDestName(),null));
            }
            map.put("dests",set);
            list.add(map);
        }
        return list;
    }

    @Override
    public List<StrategyTemplate> listByDestName(String destName) {

        return repository.findByDestName(destName);
    }

    private List<StatsResult> groupSearch(String id, String name) {
        String conditionField = "condition";
        String idField = "id";
        String nameField = "name";

        List<StatsResult> list = new ArrayList<>();

        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        //构建桶聚合字段
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        sources.add(new TermsValuesSourceBuilder(idField).field(id));
        sources.add(new TermsValuesSourceBuilder(nameField).field(name));

        //构建aggs
        CompositeAggregationBuilder aggs = new CompositeAggregationBuilder(conditionField, sources);

        //设置pageSize = 1
        builder.withPageable(PageRequest.of(0, 1));

        builder.addAggregation(aggs); //添加aggs

        //如果查询国内数据则保证countryId=1
        if (id.equals("provinceId")) {
            builder.withQuery(QueryBuilders.termQuery("countryId", "1"));
        }

        //执行查询
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        //拿到桶聚合的结果
        InternalComposite agg = (InternalComposite) page.getAggregation(conditionField);
        //获取每一个桶对象
        for (CompositeAggregation.Bucket bucket : agg.getBuckets()) {
            Map<String, Object> key = bucket.getKey();
        /* 从桶中拿到我们要的id,name,doc_count数据,封装成StatsResult对象
            {
                key : {id: xx, name: xxx},
                doc_count : xx
            }
         */
            Object idX = key.get(idField);
            Object nameX = key.get(nameField);

            StatsResult vo = new StatsResult(Long.parseLong(idX.toString()), nameX.toString(),
                    bucket.getDocCount());
            list.add(vo);
        }
        return list;
    }
}
